home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / WHEREIS.ASM < prev    next >
Assembly Source File  |  1987-05-05  |  12KB  |  518 lines

  1.     name    whereis
  2.     title    'WHEREIS -- find file'
  3.     page    55,132
  4. ;
  5. ; WHEREIS -- find file in directory structure
  6. ; by John Scotia, first published in Softalk/IBM
  7. ; modified by Ray Duncan
  8. ;
  9. lf    equ    0ah            ;ASCII line feed
  10. cr    equ    0dh            ;ASCII carriage return
  11. ff    equ    0ch            ;ASCII form feed
  12. tab    equ    09h
  13. eom    equ    '$'            ;end of message flag
  14. ;
  15.                     ;Program Segment Prefix
  16. default_fcb equ    05ch
  17. command    equ    80h     
  18. default_dta equ    080h
  19. ;
  20. ;
  21.  
  22. ; This is the format for the DOS Data Transfer Area used when DOS 2.0    
  23. ; searches for a file match in directories.                
  24.  
  25. DTA    STRUC
  26.     RESERVED    DB    21 DUP (?)
  27.     ATTRIBUTE    DB    0
  28.     TIME        DW    0
  29.     DATE        DW    0
  30.     SIZE        DD    0
  31.     NAME_FOUND    DB    13 DUP (?)
  32. DTA    ENDS
  33.  
  34. cseg    segment    para public 'CODE'
  35.  
  36.     assume     cs:cseg,ds:data,es:data,ss:stack
  37.  
  38.     page
  39.  
  40. ; This is the main program that sets up the initial conditions for    
  41. ; SDIR which, in turn, does a recursive search.        
  42. ;                                    
  43. ; Reads:    PATH_NAME                        
  44. ; Writes:    FILE_NAME                        
  45. ; Calls:    SDIR                    
  46.  
  47. whereis    proc    far
  48.  
  49.     push    ds            ;save final return
  50.     xor    ax,ax
  51.     push    ax
  52.     mov    bp,sp            ;save pointer to final return
  53.                     ; in case we want to exit
  54.                     ; inside recursive routine
  55.  
  56.     mov    ax,data            ;make data segment addressable
  57.     mov    es,ax            ;via ES
  58.  
  59.     call    infile            ;get name of search target
  60.  
  61.     mov    ax,data            ;make data segment addressable
  62.     mov    ds,ax            ;via DS
  63.     jnc    whereis1        ;jump if filename was ok
  64.                     ;filename was missing,
  65.     mov    dx,offset msg1        ;print error message and exit
  66.     mov    ah,9
  67.     int    21h
  68.     ret
  69. whereis1:
  70.     mov    ah,30h            ;check DOS version
  71.     int    21h
  72.     cmp    al,2
  73.     jae    whereis2        ;proceed, DOS 2.0 or greater
  74.     mov    dx,offset msg3        ;DOS 1.1 --- print message
  75.     mov    ah,9            ;and exit
  76.     int    21h
  77.     ret
  78. whereis2:
  79.     MOV    DI,OFFSET PATH_NAME
  80.     XOR    AL,AL            ;Search for the zero at the end
  81.     CLD                ; of PATH_NAME
  82.     MOV    CX,64            ;Max. length of scan for 0
  83.     REPNZ    SCASB
  84.     MOV    BX,DI
  85.     DEC    BX            ;DS:BX points to end of PATH_NAME
  86.     MOV    DX,0            ;Tell SDIR this is first
  87.     CALL    SDIR            ;Now do the recursive search
  88.     mov    ax,match_count        ;were any matches found?
  89.     or    ax,ax
  90.     jz    whereis8        ;no,jump
  91.     ret                ;yes,just exit
  92. whereis8:
  93.     mov    dx,offset msg2        ;no,print "no match"
  94.     mov    ah,9
  95.     int    21h
  96.     ret
  97.                     ;this is a special crash
  98.                     ;exit, which may be taken
  99.                     ;from inside recursed proc.
  100. whereis9:
  101.     mov    sp,bp
  102.     ret
  103.  
  104. whereis    endp
  105.  
  106.     page
  107.  
  108. ;  This procedure searches all the files in the current directory    
  109. ; looking for a match.  It also prints the full name for each match.    
  110. ;                                    
  111. ;    DS:BX        Pointer to end of current path name        
  112. ;    DS:DX        Old disk transfer area (DTA)            
  113. ;                                    
  114. ; Reads:    Disk Transfer Area (DTA)                
  115. ; Writes:    Disk Transfer Area (DTA)                
  116. ; Calls:    BUILD_NAME, FMATCH, PNAME        
  117. ;        NMATCH, BUILD_STAR_NAME, SSUB    
  118.  
  119. SDIR    PROC    NEAR
  120.     PUSH    SI            ;Need to restore on exit
  121.     PUSH    DX
  122.     CALL    BUILD_NAME        ;Build the absolute search name
  123.     CALL    FMATCH            ;See if there is a match here
  124.     JC    sdir2             ;No match, check subdirectories
  125.     CALL    PNAME            ;Write name of match.
  126. sdir1:
  127.     CALL    NMATCH            ;Find the next match
  128.     JC    sdir2            ;No match, search sub-directories
  129.     CALL    PNAME            ;Match, write absolute name
  130.     JMP    sdir1            ;Look for the next matching name
  131. sdir2:                    ;No match, so try sub-directories.
  132.     POP    DX            ;Restore DTA
  133.     PUSH    DX
  134.     CALL    BUILD_STAR_NAME        ;Search for all directories
  135.     CALL    FMATCH            ;Get first entry
  136.     JC    SDIR5            ;There are no entries
  137.     MOV    SI,DX            ;Put address of DTA into SI
  138.     TEST    [SI].ATTRIBUTE,10H    ;Is it a directory entry?
  139.     JNZ    SDIR4            ;Yes, then search sub-directory
  140. SDIR3:
  141.     CALL    NMATCH            ;No, then find the next match
  142.     JC    SDIR5            ;There are no more entries
  143.     TEST    [SI].ATTRIBUTE,10H    ;Is this a directory?
  144.     JZ    SDIR3            ;No, then try again
  145. SDIR4:
  146.     CMP    [SI].NAME_FOUND,'.'    ;Is this a . or .. directory?
  147.     JE    SDIR3            ;Yes, skip to next directory
  148.     CALL    SSUB            ;Search the sub-directory
  149.     PUSH    AX            ;Now reset the DTA
  150.     MOV    AH,1AH
  151.     INT    21H
  152.     POP    AX
  153.     JMP    SDIR3
  154.  
  155. SDIR5:
  156.     POP    DX
  157.     POP    SI
  158.     RET
  159. SDIR    ENDP
  160.  
  161.     page
  162.  
  163. ; This procedure searches the subdirectory whos name is in the DTA    
  164. ;                                    
  165. ;    DS:BX        End of the current path name            
  166. ;    DS:[DX].NAME_FOUND    Name of subdirectory for search        
  167. ; Reads:    PATH_NAME                        
  168. ; Writes:    PATH_NAME                        
  169. ; Calls:    SDIR                    
  170.  
  171. SSUB    PROC    NEAR
  172.     PUSH    DI
  173.     PUSH    SI
  174.     PUSH    AX
  175.     PUSH    BX
  176.     CLD                ;Set for increment
  177.     MOV    SI,DX            ;Put address of DTA into SI
  178.     ADD    SI,OFFSET NAME_FOUND    ;Set to start of sub-directory name
  179.     MOV    DI,BX            ;DS:DI -- 0 at end of path name
  180. ssub1:                    ;Copy sub-directory to path name
  181.     LODSB                ;Copy one character
  182.     STOSB
  183.     OR    AL,AL            ;Was it a 0?
  184.     JNZ    ssub1            ;No, keep copying
  185.     MOV    BX,DI            ;Set BX to end of new path name
  186.     STD                ;Set flag for decrement
  187.     STOSB                ;Store a 0 at end of string
  188.     MOV    AL,'\'
  189.     STOSB                ;Place '\' at end of path name
  190.     CALL    SDIR            ;Search this new path
  191.     POP    BX            ;Restore the old end-of-path
  192.     MOV    BYTE PTR [BX],0        ;And store a zero here
  193.     POP    AX
  194.     POP    SI
  195.     POP    DI
  196.     RET
  197. SSUB    ENDP
  198.  
  199.     page
  200.  
  201. ; This procedure prints the matched name after the path name        
  202. ;
  203. ;    DS:DX        Pointer to current disk transfer area        
  204. ;                                    
  205. ; Reads:    PATH_NAME, NAME_FOUND (in DTA)                
  206. ; Calls:    pasciiz, CRLF                    
  207.  
  208. PNAME    PROC    NEAR
  209.     PUSH    AX
  210.     PUSH    DX
  211.     MOV    DX,OFFSET PATH_NAME
  212.     MOV    AL,[BX]            ;Save character at end of path
  213.     MOV    BYTE PTR [BX],0        ;Set for end of string    
  214.     CALL    pasciiz
  215.     MOV    [BX],AL            ;Restore character
  216.     POP    DX            ;Recover old pointer
  217.     PUSH    DX
  218.     ADD    DX,OFFSET NAME_FOUND
  219.     CALL    pasciiz
  220.     cmp    byte ptr switch,'g'    ;global switch set?
  221.     je    pname2            ;yes,keep searching
  222.                     ;no, check if user wants 
  223.                     ;to keep looking.
  224.     push    dx            ;save current DTA
  225.     mov    dx,offset msg4        ;print 'More? '
  226.     mov    ah,9
  227.     int    21h
  228.     mov    ah,7            ;read console without echo
  229.     int    21h    
  230.     or    al,20h            ;fold to lower case
  231.     cmp    al,'y'            ;must be y, anything else exits 
  232.     je    pname1
  233.     jmp    whereis9        ;take crash exit
  234. pname1:    mov    dl,al            ;if Y,echo it
  235.     mov    ah,2
  236.     int    21h
  237.     pop    dx            ;restore pointer to DTA
  238. pname2:    CALL    CRLF
  239.     inc    match_count        ;count names displayed
  240.     POP    DX
  241.     POP    AX
  242.     RET
  243. PNAME    ENDP
  244.  
  245.     page
  246.  
  247. ;  This procedure builds an absolute search name from PATH_NAME        
  248. ; followed by FILE_NAME.                        
  249. ;                                    
  250. ; Reads:    FILE_NAME                        
  251. ; Calls:    BUILD        to build the name            
  252.  
  253. BUILD_NAME    PROC    NEAR
  254.     PUSH    SI
  255.     MOV    SI,OFFSET FILE_NAME
  256.     CALL    BUILD
  257.     POP    SI
  258.     RET
  259. BUILD_NAME    ENDP
  260.  
  261. BUILD_STAR_NAME        PROC    NEAR
  262.     PUSH    SI
  263.     MOV    SI,OFFSET STAR_NAME
  264.     CALL    BUILD
  265.     POP    SI
  266.     RET
  267. BUILD_STAR_NAME        ENDP
  268.  
  269. ; This procedure appends the string at DS:SI to PATH_NAME in        
  270. ; PATH_NAME.  It knows where the path name ends from knowing how    
  271. ; long PATH_NAME is.                            
  272. ;                                    
  273. ;    DS:SI        Name of file                    
  274. ;    DS:BX        End of PATH_NAME                
  275. ;                                    
  276. ; Reads:    DS:SI                            
  277. ; Writes:    PATH_NAME                        
  278.  
  279. BUILD    PROC    NEAR
  280.     PUSH    AX
  281.     PUSH    DI
  282.     MOV    DI,BX
  283.     CLD                ;Set direction for increment
  284. build1:
  285.     LODSB                ;Copy one character of name
  286.     STOSB
  287.     OR    AL,AL            ;End of string yet?
  288.     JNZ    build1            ;No, keep copying
  289.     POP    DI
  290.     POP    AX
  291.     RET
  292. BUILD    ENDP
  293.  
  294.     page
  295.  
  296. ;  This procedure finds the first match between the name given by    
  297. ; DS:DX and the directory entries found in the directory PATH_NAME.    
  298. ;                                    
  299. ;    DS:DX        Pointer to current disk transfer area        
  300. ; Returns:                                
  301. ;    CF    0    A match was found                
  302. ;        1    No match found                    
  303. ;    AX        Error code returned:                
  304. ;        2    File not found                    
  305. ;        18    No more files                    
  306. ;    DS:DX        Pointer to new disk transfer area        
  307. ;                                    
  308. ; Reads:    PATH_NAME                        
  309. ; Writes:    dbuff
  310.  
  311. FMATCH    PROC    NEAR
  312.     PUSH    CX
  313.     CMP    DX,0            ;First one?
  314.     JA    ALLOCATE        ;No, then allocate space
  315.     MOV    DX,OFFSET dbuff-TYPE DTA
  316. allocate:
  317.     add    dx,type dta        ;no, then allocate room for new DTA
  318.     MOV    CX,10H            ;Search attribute for files and dirs.
  319.     MOV    AH,1AH            ;Set disk transfer address
  320.     INT    21H
  321.     PUSH    DX            ;Need DX for address of search name
  322.     MOV    DX,OFFSET PATH_NAME
  323.     MOV    AH,4EH            ;Call for "find first match"
  324.     INT    21H
  325.     POP    DX
  326.     POP    CX
  327.     RET                ;Return with carry flag info
  328. FMATCH    ENDP
  329.  
  330.  
  331.     page
  332.  
  333. ; Get next match for filename
  334. ; (very similar to Get first match routine)
  335.  
  336. ; Returns:                                
  337. ;    CF    0    A match was found                
  338. ;        1    No match found                    
  339. ;    AX        Error code returned:                
  340. ;        2    File not found                    
  341. ;        18    No more files                    
  342. ;                                    
  343. ; Reads:    PATH_NAME                        
  344. ; Writes:    dbuff                    
  345.  
  346. NMATCH    PROC    NEAR
  347.     PUSH    CX
  348.     PUSH    DX
  349.     MOV    DX,OFFSET PATH_NAME
  350.     MOV    CX,10H            ;Attribute for files and directories
  351.     MOV    AH,4FH            ;Call for "Find next match"
  352.     INT    21H
  353.     POP    DX
  354.     POP    CX
  355.     RET                ;Return with carry flag intact
  356. NMATCH    ENDP
  357.  
  358.  
  359.     page
  360.  
  361. ;  Send CRLF sequence to the screen.    
  362.  
  363. CRLF    PROC    NEAR
  364.     PUSH    AX
  365.     PUSH    DX
  366.     MOV    AH,02
  367.     MOV    DL,0AH
  368.     INT    21H
  369.     MOV    DL,0DH
  370.     INT    21H
  371.     POP    DX
  372.     POP    AX
  373.     RET
  374. CRLF    ENDP
  375.  
  376.     page
  377.  
  378. ;  Display ASCIIZ string 
  379. ;  Call with DS:DX = string addr
  380.  
  381. pasciiz    PROC    NEAR
  382.     PUSH    AX
  383.     PUSH    DX
  384.     PUSH    SI
  385.     CLD                ;Set direction for increment
  386.     MOV    SI,DX            ;Set up pointer to string
  387.     MOV    AH,2
  388. pasciiz1:
  389.     LODSB                ;Get character
  390.     or    al,al            ;if zero,all done
  391.     jz    pasciiz2
  392.     MOV    DL,AL
  393.     INT    21H            ;Write one character
  394.     jmp    pasciiz1        ;loop till string exhausted
  395. pasciiz2:
  396.     POP    SI
  397.     POP    DX
  398.     POP    AX
  399.     RET
  400. pasciiz    ENDP
  401.  
  402.     page
  403.  
  404.  
  405. infile    proc    near        ;process name of input file
  406.                 ;DS:SI <- addr command line    
  407.     mov    si,offset command
  408.                 ;ES:DI <- addr filespec buffer
  409.     mov    di,offset file_name
  410.     cld
  411.     lodsb            ;any command line present?
  412.     or    al,al        ;return error status if not.
  413.     jz    infile4
  414. infile1:                 ;scan over leading blanks
  415.     lodsb            ;to file name
  416.     cmp    al,cr        ;if we hit carriage return
  417.     jz    infile4     ;filename is missing.
  418.     cmp    al,20h        ;is this a blank?
  419.     jz    infile1        ;if so keep scanning.
  420.     xor    ah,ah        ;reset "." found flag
  421.                 ;found first char of name
  422. infile2:             
  423.     cmp    al,'\'        ;if slash,reset "." flag
  424.     jne    infile22
  425.     xor    ah,ah
  426. infile22:            ;check if extension specified
  427.     cmp    al,'.'
  428.     jne    infile24
  429.     inc    ah
  430. infile24:            ;
  431.     stosb            ;move last char. to output
  432.                 ;file name buffer. 
  433.     lodsb            ;check next character, found
  434.     cmp    al,cr        ;carriage return yet?      
  435.     je    infile3        ;yes,exit with success code
  436.     cmp    al,'/'        ;or if we hit a switch delimiter
  437.     jne    infile26
  438. infile25:
  439.     lodsb            ;get the switch char and save it
  440.     or    al,20h        ;force to lower case
  441.     mov    byte ptr es:switch,al
  442.     jmp    infile3        ;then jump to finish up
  443. infile26:
  444.     cmp    al,20h        ;is this a blank?
  445.     jne     infile2        ;if not keep moving chars.
  446. infile27:
  447.     lodsb            ;search up to end, in case of switch
  448.     cmp    al,'/'
  449.     je    infile25    ;found switch,go save it
  450.     cmp    al,cr
  451.     jne    infile27    ;otherwise, fscan until CR found
  452. infile3:             ;found end of input name
  453.     or    ah,ah        ;was "." found?
  454.     jnz    infile35    ;yes,jump
  455.     mov    al,'.'        ;no,force ext to wildcard
  456.     stosb
  457.     mov    al,'*'
  458.     stosb
  459. infile35:
  460.     xor    al,al        ;store trailing null byte
  461.     stosb            ;exit with CY=0 as success flag
  462.     clc            
  463.     ret
  464.  
  465. infile4:             ;exit with carry =1
  466.     stc            ;for error flag
  467.     ret
  468. infile  endp 
  469.  
  470. cseg    ends
  471.  
  472.     page
  473.  
  474. data         segment para public 'DATA'
  475.  
  476. STAR_NAME    DB    '*.*',0
  477.  
  478. PATH_NAME    DB    '\',0
  479.         DB    80 DUP (0)    ;Space for 64 character path name
  480.                     ; and 13 character file name
  481.  
  482. FILE_NAME    DB    13 DUP (0)    ;Save room for full DOS file name
  483.  
  484. msg1        db    cr,lf
  485.         db    'Missing file name.'
  486.         db    cr,lf,eom
  487.  
  488. msg2        db    cr,lf
  489.         db    'No match found.'
  490.         db    cr,lf,eom
  491.  
  492. msg3        db    cr,lf
  493.         db    'Requires DOS version 2.0 or greater.'
  494.         db    cr,lf,eom
  495.  
  496. msg4        db    tab,'  More (y/n) ? ',eom
  497.  
  498. match_count    dw    0        ;number of filenames matching
  499.                     ;input filespec
  500.  
  501. switch        db    0        ;char following / saved here
  502.  
  503. dbuff        equ    $        ;this starts the scratch area
  504.                     ;which will be used as search
  505.                     ;buffers.  It is right under
  506.                     ;the stack, which is made very
  507.                     ;large to give it room.
  508.  
  509. data        ends 
  510.  
  511.  
  512. stack    segment    para stack 'STACK'
  513.     db    32768 dup (?)
  514. stack    ends
  515.  
  516.  
  517.     end    whereis
  518.